package com.example.widget_lib.widget.wave;

import com.example.widget_lib.utils.PxUtil;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.*;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.app.Context;
import ohos.app.dispatcher.TaskDispatcher;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Size;

/**
 * 圆形背景水波纹进度效果
 * <p>
 * 1、setXfermode必须要设置上层图形的画笔中
 * 2、用onDraw方法中的canvas设置setXfermode没有效果
 * 3、setXfermode必须要在画笔用到之前设置
 *
 * @autor hongbing
 * @date 2019-07-22
 */
public class CircleWaveView extends Component implements Component.DrawTask {


    /**
     * PorterDuff的16种模式
     * <p>
     * 源像素：当前设置xfermode的
     * 目标像素：固定不变的
     *
     * <p>
     * 1、CLEAR：清除画笔所绘制的内容
     * 2、SRC_ATOP：丢弃未覆盖目标像素的源像素。
     * 3、SRC_IN：原始图 & 操作图相交的部分
     * 4、SRC_OUT：原始图 & 操作图除了相交的部分
     * 5、6、SRC，SRC_OVER：原始图 & 操作图覆盖在上面
     * 7、XOR：原始图 & 操作图除了相交的部分
     * 8、SCREEN：添加源像素和目标像素，然后减去源像素乘以目标
     * 9、OVERLAY：根据目标颜色将源和目标相乘或屏幕显示
     * 10、MULTIPLY：将源像素和目标像素相乘。
     * 11、LIGHTEN：保留源像素和目标像素的最大分量。
     * 12、DST：丢弃操作图，是原始图保持不变
     * 13、DST_OUT：保留源像素未覆盖的目标像素
     * 14、DST_OVER：源像素在目标像素的后面
     * 15、DST_IN：
     * 16、DST_ATOP：
     */

    /**
     * 弧长高度
     */
    private static final int ARC_H = (int) PxUtil.vp2px(32);

    private static final String TAG = "CircleWaveView";
    private Paint mCirclePaint;
    private Paint mWavePaint;
    //    private PorterDuffXfermode mDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
    private BlendMode mDuffXfermode = BlendMode.SRC_IN;

    private Canvas mCanvas;
    private PixelMap mBitmap;

    private int mWidth;
    private int mHeight;
    private int mX, mY;
    private int mPercent;
    private boolean isLft;
    private Path mPath, mPath2;
    private TaskDispatcher handler;
    private int mStart;

    public CircleWaveView(Context context, AttrSet attrSet) {
        super(context, attrSet);
        handler = context.getUITaskDispatcher();

        mCirclePaint = new Paint();
        mCirclePaint.setColor(new Color(Color.getIntColor("#990000FF")));
        mCirclePaint.setStrokeWidth(10);
        mCirclePaint.setAntiAlias(true);
        mCirclePaint.setDither(false);

        mWavePaint = new Paint();
        mWavePaint.setColor(new Color(Color.getIntColor("#7F0000FF")));
        mWavePaint.setAntiAlias(true);
        mWavePaint.setDither(false);

        mPath = new Path();
        mPath2 = new Path();

        setBindStateChangedListener(new BindStateChangedListener() {
            @Override
            public void onComponentBoundToWindow(Component component) {
                calculate();
                addDrawTask(CircleWaveView.this);
            }

            @Override
            public void onComponentUnboundFromWindow(Component component) {

            }
        });
    }

    @Override
    public void addDrawTask(DrawTask task) {
        super.addDrawTask(task);
        task.onDraw(this, mCanvasForTaskOverContent);
    }

    private void calculate() {
        mWidth = getWidth();
        mHeight = getHeight();
        // 设置画布大小
        PixelMap.InitializationOptions options = new PixelMap.InitializationOptions();
        options.size = new Size(mWidth, mHeight);
        options.pixelFormat = PixelFormat.ARGB_8888;
        mBitmap = PixelMap.create(options);
        mCanvas = new Canvas(new Texture(mBitmap));

        mY = mHeight;
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (mPercent <= 0) {
            //TODO
//            mBitmap.writePixels(Color.TRANSPARENT.getValue());
//            mBitmap.writePixels(Color.getIntColor("#00000000"));
            mCanvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, mCirclePaint);
        } else {
            float target;
            if (mPercent < 50) {
                // 计算起始点
                // (mWidth * mPercent / 50f) 计算进度横向长度
                mStart = (int) (mWidth / 2 - (mWidth * mPercent / 50f) / 2);
                target = mWidth * mPercent / 50f;
                if (mX > target + ARC_H * 2 + 4) { // ARC_H * 2 弧长,mX在经度横切面不断的更新控制点x坐标，起到动画效果
                    isLft = true;
                } else if (mX < -ARC_H * 2 - 4) {
                    isLft = false;
                }
            } else if (mPercent == 50) {
                mStart = 0;
                target = mWidth;
                if (mX > target + 4) { // ARC_H * 2 弧长,mX在经度横切面不断的更新控制点x坐标，起到动画效果
                    isLft = true;
                } else if (mX < -4) {
                    isLft = false;
                }
            } else {
                mStart = (int) (mWidth / 2 - (mWidth - mWidth * mPercent / 100f) / 2);
                target = mWidth - mWidth * mPercent / 100f;
                if (mX > target + ARC_H * 2 + 4) { // ARC_H * 2 弧长,mX在经度横切面不断的更新控制点x坐标，起到动画效果
                    isLft = true;
                } else if (mX < -ARC_H * 2 - 4) {
                    isLft = false;
                }
            }

            if (isLft) {
                mX = mX - 8;
            } else {
                mX = mX + 8;
            }
            mY = (int) ((1 - mPercent / 100f) * mHeight);

            mPath.reset();
            mPath.moveTo(0, mY);
            mPath.cubicTo(new Point(mStart + mX, mY + ARC_H), new Point(mStart + mX, mY - ARC_H), new Point(mWidth, mY));
            mPath.lineTo(mWidth, mHeight);
            mPath.lineTo(0, mHeight);
            mPath.close();

            //TODO
//            mBitmap.writePixels(Color.getIntColor("#00000000"));
            mCanvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, mCirclePaint);

            mWavePaint.setColor(new Color(Color.getIntColor("#990000FF")));
            mWavePaint.setBlendMode(mDuffXfermode);
            mCanvas.drawPath(mPath, mWavePaint);
            mWavePaint.setBlendMode(null);

//            mPath2.reset();
//            mPath2.moveTo(0, mY);
//            mPath2.cubicTo(mStart + mX, mY + ARC_H * 2, mStart + mX, mY - ARC_H * 2, mWidth, mY);
//            mPath2.lineTo(mWidth, mHeight);
//            mPath2.lineTo(0, mHeight);
//            mPath2.close();
//
//            mWavePaint.setColor(Color.parseColor("#990000FF"));
//            mWavePaint.setXfermode(mXfermode);
//            mCanvas.drawPath(mPath2, mWavePaint);
//            mWavePaint.setXfermode(null);
        }
        canvas.drawPixelMapHolder(new PixelMapHolder(mBitmap), 0, 0, new Paint());
        handler.delayDispatch(this::invalidate, 10);
    }

    public void setPercent(int percent) {
        mPercent = percent;
    }
}
